1. /* slfllmul.cpp by K.Tsuru */
  2. // function ID = 209 DRADIX , BRADIX
  3. /************************************************************************
  4. SLong class
  5. It returns m*n.
  6. When the number of figures is equal to 2^p+a,where a is small, the direct
  7. use of FFT multiplication needs a processing time twice over in comparison
  8. with 2^p figures. Then it is splited into 2^p and "a" figures.
  9. *************************************************************************/
  10. #ifndef SN_H
  11. #include "sn.h"
  12. #endif
  13. static const char* const func = "LLMult";
  14. // void (*SLong::pfHHMult)(const SLong& x, const SLong& y, SLong& z) = NULL; // deleted since version 2.192
  15. bool SLong::usesKaratsuba_HH_Mult = true;
  16. /*
  17. |m| >= |n| > 0
  18. For the simplicity of algorithm the longer number is taken as the multiplicand.
  19. */
  20. SLong LLMult(const SLong& m, const SLong& n){
  21. // make sin table on memory
  22. #if USES_SIN_TABLE_FFT
  23. if(FFTSineTableSize() == 0) MakeSinTable(FFT_MAX_SIZE_BITS);
  24. #endif
  25. if(!m.FFTUse()) return NLLMult(m, n);
  26. if( m.Head() < n.Head() ) return LLMult(n, m); //n is longer.
  27. // |n| == 1 ?
  28. if(n.IsOne()){
  29. if(n.Sign() > 0) return m; // n == 1
  30. return -m; // n == -1
  31. }
  32. //It checks the signs.
  33. int sgn = m.Sign(209)*n.Sign(209);
  34. SLong result(m.Type(), 0); // figure.size() = 0;
  35. if(!sgn){ // m = 0 or n = 0
  36. result.SetZero();
  37. return result;
  38. }
  39. uint mh = m.aHead, mt = m.aTail, nh = n.aHead, nt = n.aTail;
  40. uint m_fig = mh + 1, n_fig = nh + 1; // the numbers of figures of m and n
  41. /*
  42. It checks the overflow error.
  43. The size of result is less than or equal to (m_fig+n_fig),
  44. e.g. 10*10 = 100, 99*99 = 9801
  45. Mar 26, 2001
  46. I changed the condition below from "(m_fig + n_fig) >= m.MaxSize()".
  47. */
  48. if( (m_fig + n_fig) > m.MaxSize() ) m.SetError( m.OVERFLOW_ERR, func, 209);
  49. #if 1
  50. //It can be reduced into (multi-precision number)*(short one)?
  51. // ver. 2.17
  52. if( mh - mt < 2 ){ // m is short less than two figures. m=X*R^mt(R:radix)
  53. ulong d = (ulong)m.figure(mt);
  54. if(mh > mt) d += m.Radix()*(ulong)m.figure(mt+1);
  55. if( d <= n.SlOpMaxValue() ){
  56. if(d != 1) result = LsMult(n, d);
  57. else result = n; //d==1, m=1*R^mt>1
  58. result.SetSign(sgn);
  59. if(mt) result.ShiftArray((int)mt); //It multiplies by R^mt.
  60. return result;
  61. }
  62. return NLLMult(m, n);
  63. }
  64. if( nh - nt < 2 ){ // n is short less than two figures. n=X*R^nt(R:radix)
  65. ulong d = (ulong)n.figure(nt);
  66. if(nh > nt) d += n.Radix()*(ulong)n.figure(nt+1);
  67. if( d <= m.SlOpMaxValue() ){
  68. if(d != 1) result = LsMult(m, d);
  69. else result = m; //d==1, n=1*R^nt>1
  70. result.SetSign(sgn);
  71. if(nt) result.ShiftArray((int)nt); //It multiplies by R^nt.
  72. return result;
  73. }
  74. return NLLMult(m, n);
  75. }
  76. #endif
  77. if(m.Type() != n.Type()) m.SetError(m.RADIX_ERR, func, 209);
  78. //m and/or n is abcd00......0 ?
  79. //mt and nt has number of last zeros.
  80. //A quarter and over of all figures are equal to zero.
  81. bool mHasManyZero = ( m_fig < 4*mt ) , nHasManyZero = ( n_fig < 4*nt );
  82. if( mHasManyZero || nHasManyZero){
  83. SLong M, N;
  84. if(mHasManyZero && !nHasManyZero){
  85. result.SLCutOut(M, m, mt, mh - mt +1);
  86. result = LLMult(M, n); //recursive call
  87. result.ShiftArray((int)mt);
  88. return result;
  89. }else if(!mHasManyZero && nHasManyZero){
  90. result.SLCutOut(N, n, nt, nh - nt +1);
  91. result = LLMult(m, N);
  92. result.ShiftArray((int)nt);
  93. return result;
  94. }
  95. result.SLCutOut(M, m, mt, mh - mt +1);
  96. result.SLCutOut(N, n, nt, nh - nt +1);
  97. result = LLMult(M, N);
  98. result.ShiftArray( int(mt + nt) );
  99. return result;
  100. }
  101. //If n has small figures, a normal method is called.
  102. if( (nh - nt +1) < m.FFTMinSize()) return NLLMult(m, n);
  103. uint mf2 = ceilpow2(m_fig), nf2 = ceilpow2(n_fig), fft_sz = 2*mf2;
  104. uint divN = mf2/nf2; //a ratio of figures
  105. //If a statement m.HHMultMode(m.hhMultMode); is used, the function KHHMult() is linked.
  106. // if(m.pfHHMult == NULL) m.pfHHMult = NHHMult;
  107. //In the unit of "nf2" the figures of m and n are diffrent each other.
  108. //m is divided by the figures of n and calculate the product.
  109. if( (nf2 > 256u) && (divN > 1) ) return DivLLMult(m, n);
  110. //Here (mf2 == nf2) && (m_fig >= n_fig)
  111. //When the upper half of n has small figures.
  112. // Removed on 14 Sep, 2000
  113. // up_fig = n_fig - nf2/2;
  114. //printf("fft_sz=%u,divN=%u m.Head()=%u, n.Head()=%u\n",fft_sz, divN, m.Head(), n.Head());
  115. // if((divN==1) && (up_fig < (nf2/16))) return DivTwoPartsLLMult(m, n);
  116. //FFT multiplication
  117. if( fft_sz <= m.FFTMaxArraySize() ){ //It needs one time.
  118. m.fftArraySize = fft_sz;
  119. result.LLMultFFT(m, n, result, m.fftArraySize );
  120. // result = NLLMult(m, n);
  121. } else { //It needs some times.
  122. m.fftArraySize = m.FFTMaxArraySize();
  123. if(m.UsesKaratsubaMult()) result.KaratsubaHHMult(m, n, result);
  124. // if(SLong::hhMultMode == SLong::Karatsuba_HH_MULT) result.DisKHHMult(m, n, result);
  125. else result.NHHMult(m, n, result);
  126. // (*m.pfHHMult)(m, n, result);
  127. }
  128. result.fftArraySize = FFTSize(); //decided in LLMultFFT()
  129. result.SetSign( sgn );
  130. return result;
  131. }

slfllmul.cpp : last modifiled at 2017/09/21 10:23:28(5,077 bytes)
created at 2017/10/07 10:26:49
The creation time of this html file is 2017/11/09 14:52:03 (Thu Nov 09 14:52:03 2017).